import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { PaginationDto } from 'src/common/dto/pagination.dto';
import { ToolsService } from 'src/utils/tools.service';
import { DataSource, Repository } from 'typeorm';
import { RoleEntity } from '../role/entities/role.entity';
import { AddRoleDto } from './dto/add-role.dto';
import { CreateDepartmentDto } from './dto/create-department.dto';
import { UpdateDepartmentDto } from './dto/update-department.dto';
import { DepartmentEntity } from './entities/department.entity';

@Injectable()
export class DepartmentService {
  @InjectRepository(DepartmentEntity)
  private readonly departmentRepository: Repository<DepartmentEntity>;

  @InjectDataSource()
  private readonly dataSource: DataSource;

  async create(createDepartmentDto: CreateDepartmentDto) {
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      const manager = await queryRunner.manager; //使用事务
      const department = new DepartmentEntity();
      department.departmentname = createDepartmentDto.departmentname;
      await manager.save(department);
      return department;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async findAll(departmentname: string, pagination: PaginationDto) {
    try {
      const res = await this.departmentRepository
        .createQueryBuilder()
        .from(DepartmentEntity, 'department')
        .setParameters({
          param: '%' + departmentname + '%',
        })
        .where('department.departmentname LIKE :param')
        .orderBy('department.created_at', 'DESC') //DESC ASC
        .skip(pagination.currentPage * pagination.pageSize)
        .take(pagination.pageSize)
        .leftJoinAndSelect('department.roles', 'roles')
        .select(['department', 'roles'])
        .getManyAndCount();
      return res;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  findOne(id: number) {
    return `This action returns a #${id} department`;
  }

  async update(id: string, updateDepartmentDto: UpdateDepartmentDto) {
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      const manager = await queryRunner.manager; //使用事务
      const department = new DepartmentEntity();
      department.id = id;
      department.departmentname = updateDepartmentDto.departmentname;
      await manager.save(department);
      return department;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async remove(id: string) {
    try {
      await this.departmentRepository
        .createQueryBuilder()
        .delete()
        .from(DepartmentEntity)
        .where('id = :id', { id: id })
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async addRole(addRoleDto: AddRoleDto) {
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      const manager = await queryRunner.manager; //使用事务
      const department = await manager
        .getRepository(DepartmentEntity)
        .createQueryBuilder('department')
        .where('department.id = :id', {
          id: addRoleDto.departmentId,
        })
        .getOne();
      if (!department) {
        throw new Error('部门不存在');
      }
      if (addRoleDto.roleIds.length > 0) {
        const roles = [];
        for (let i = 0; i < addRoleDto.roleIds.length; i++) {
          const listOne = await manager
            .getRepository(RoleEntity)
            .createQueryBuilder('role')
            .where('role.id = :id', {
              id: addRoleDto.roleIds[i],
            })
            .getOne();

          if (!listOne) ToolsService.fail('角色id不存在');
          roles.push(listOne);
        }
        const departmentEntity = new DepartmentEntity();
        departmentEntity.id = addRoleDto.departmentId;
        departmentEntity.roles = roles;
        await manager.save(departmentEntity);
        return departmentEntity;
      } else {
        const departmentEntity = new DepartmentEntity();
        departmentEntity.id = addRoleDto.departmentId;
        departmentEntity.roles = [];
        await manager.save(departmentEntity);
        return departmentEntity;
      }
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async findOwnerRoles(userId: string) {
    try {
      const user = await this.departmentRepository
        .createQueryBuilder()
        .from(DepartmentEntity, 'department')
        .where('department.id = :id', { id: userId })
        .leftJoinAndSelect('department.roles', 'roles')
        .select(['department', 'roles'])
        .getOneOrFail();
      return user.roles;
    } catch (error) {
      ToolsService.fail(error);
    }
  }
}
